#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <nice2d/spriteimagedecorator.h>
#include <nice2d/application.h>
#include <nice2d/components/imagemanager.h>

IMPLEMENT_OBJECT(SpriteImageDecorator,SpriteDecorator)

class SpriteImageDecoratorData
{
public:
    sf::Sprite sprite;
    float scale = 1.0f;
};

SpriteImageDecorator::SpriteImageDecorator():
    data(new SpriteImageDecoratorData())
{
}

SpriteImageDecorator::~SpriteImageDecorator()
{
}

void SpriteImageDecorator::setImage(const std::string &file, const sf::IntRect &area)
{
    auto imageManager = GET_COMPONENT(Application::getInstance(),ImageManager);
    auto texture = imageManager->loadTextureFromFile(file,area);
    assert(texture);

    data->sprite.setTexture(*texture.get(),true);
    update();
}

void SpriteImageDecorator::setColor(const sf::Color &color)
{
    data->sprite.setColor(color);
}

sf::Color SpriteImageDecorator::getColor() const
{
    return data->sprite.getColor();
}

void SpriteImageDecorator::setScale(float scale)
{
    if(scale > 0.0f)
    {
        data->scale = scale;
        update();
    }
}

float SpriteImageDecorator::getScale() const
{
    return data->scale;
}

void SpriteImageDecorator::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
    target.draw(data->sprite,states);
}

void SpriteImageDecorator::update()
{
    auto sprite = getSprite();
    if(sprite.expired())
        return;

    auto box = sprite.lock()->getBoundingBox();

    data->sprite.setRotation(getRotate());
    data->sprite.setScale(getScale(),getScale());
    auto spriteBox = data->sprite.getGlobalBounds();
    auto position = Entity::adjustPosition(box, {spriteBox.width,spriteBox.height},getHAligment(),getVAlignment(), 0.0f, 0.0f);
    position.x -= box.left;
    position.y -= box.top;
    position.x -= spriteBox.left;
    position.y -= spriteBox.top;
    position += getOffset();
    data->sprite.setPosition(position);
}

PTree SpriteImageDecorator::serialize()
{
    PTree node;
    return node;
}

void SpriteImageDecorator::deserialize(const PTree &node)
{

}

void SpriteImageDecorator::updateAnchor()
{
    update();
}
